package com.ykh.service.impl;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ykh.pojo.dto.PageParams;
import com.ykh.pojo.dto.VideoDto;
import com.ykh.pojo.po.Category;
import com.ykh.pojo.po.User;
import com.ykh.pojo.po.Video;
import com.ykh.mapper.VideoMapper;
import com.ykh.pojo.vo.ErrorCode;
import com.ykh.pojo.vo.Result;
import com.ykh.pojo.vo.VideoPathVo;
import com.ykh.pojo.vo.VideoVo;
import com.ykh.service.CategoryService;
import com.ykh.service.UserService;
import com.ykh.service.VideoService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ykh.util.*;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import java.io.UnsupportedEncodingException;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;

/**
 * <p>
 *  服务实现类
 * </p>
 *
 * @author ykh
 * @since 2023年10月26日
 */
@Service
public class VideoServiceImpl extends ServiceImpl<VideoMapper, Video> implements VideoService {
    @Autowired
    private QiniuUtils qiniuUtils;

    @Autowired
    private VideoMapper videoMapper;

    @Autowired
    private UserService userService;

    @Autowired
    private CategoryService categoryService;

    //redis的对象
    @Autowired
    private RedisTemplate<String,String> redisTemplate;


//    @Autowired
//    private RedisTemplate<String, Object> redisTemplate;

    @Override
    @Transactional
    public Result uploadVedio(VideoDto videoDto) {
        /**
         * 1.上传视频文件, 上传成功后得到视频文件的URL
         * 2.使用工具类获取视频的时长
         * 3.将视频的URL等信息存入数据库
         */
        User user = UserThreadLocal.get();
        if (user == null) {
            return Result.fail(ErrorCode.NO_LOGIN.getCode(), ErrorCode.NO_LOGIN.getMsg());
        }
        MultipartFile videoFile = videoDto.getVideoFile();
        String fileName =  videoFile.getOriginalFilename();
        String key = qiniuUtils.upload(videoFile, fileName);
        if(key == null){
            return Result.fail(ErrorCode.VIDEO_UPLOAD_FAIL.getCode(), ErrorCode.VIDEO_UPLOAD_FAIL.getMsg());
        }
        //对上传的视频进行转码
        String newKey = qiniuUtils.transcoding(key);

        //更新DB
        Video video = new Video();
        video.setVideoUrl(newKey);
        video.setVideoTitle(videoDto.getVideoTitle());
        video.setCategoryId(videoDto.getCategoryId());
        video.setDuration(VideoUtil.getDurationBackString(videoFile));
        video.setSummary(videoDto.getSummary());
        video.setCoverUrl("");
        video.setUserAccount(user.getAccount());
        video.setCreateTime(LocalDateTime.now());
        videoMapper.insert(video);
        return Result.success(new VideoPathVo(video.getVideoId(), Constant.VIDEO_URL+ "/" + newKey));
    }

    /**
     * 获取单个视频资源
     * @param videoId
     * @return
     */
    @Override
    public Result getVideo(Integer videoId) throws UnsupportedEncodingException {
        LambdaQueryWrapper<Video> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Video::getVideoId, videoId);
        Video video = videoMapper.selectOne(queryWrapper);
        if(video == null){
            return Result.fail(ErrorCode.NO_EXIST_VIDEO.getCode(), ErrorCode.NO_EXIST_VIDEO.getMsg());
        }
        String videoKey = video.getVideoUrl();
        String videoLink = qiniuUtils.fileUrl(videoKey);

        //增加视频播放量
        increasePlayCount(videoId);
        video.setVideoUrl(videoLink);
        return Result.success( copy(video));

    }

    /**
     * 分页获取视频资源
     * @param pageParams
     * @return
     */
    @Override
    public List<VideoVo> getVideoList(@RequestBody PageParams pageParams) {
        LambdaQueryWrapper<Video> queryWrapper = new LambdaQueryWrapper<>();
        String condition = pageParams.getCondition();
        //添加条件搜索
        if(condition != null){
            queryWrapper.like(Video::getVideoTitle, condition);
            queryWrapper.orderByDesc(Video::getCreateTime);
        }
        Page<Video> page = new Page<>(pageParams.getPage(), pageParams.getPageSize());
        IPage<Video> videoIPage = videoMapper.selectPage(page, queryWrapper);
        return copyList( videoIPage.getRecords());
    }

    /**
     * 根据用户ID分页获取用户视频作品
     * @param account
     * @return
     */
    @Override
    public List<VideoVo> getUserVideoList(PageParams pageParams, String account) {
        LambdaQueryWrapper<Video> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Video::getUserAccount, account);
        queryWrapper.orderByDesc(Video::getCreateTime);
        Page<Video> page = new Page<>(pageParams.getPage(), pageParams.getPageSize());
        IPage<Video> videoIPage = videoMapper.selectPage(page,queryWrapper);
        return copyList( videoIPage.getRecords());
    }

    /**
     * 根据分类id查找视频
     * @param pageParams
     * @param categoryId
     * @return
     */
    @Override
    public List<VideoVo> getVideoListByCategory(PageParams pageParams, Integer categoryId) {
        LambdaQueryWrapper<Video> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Video::getCategoryId, categoryId);
        String condition = pageParams.getCondition();
        //添加条件搜索
        if(condition != null){
            queryWrapper.like(Video::getVideoTitle, condition);
            queryWrapper.orderByDesc(Video::getCreateTime);
        }
        Page<Video> page = new Page<>(pageParams.getPage(), pageParams.getPageSize());
        IPage<Video> videoIPage = videoMapper.selectPage(page,queryWrapper);
        if(videoIPage.getSize()==0){
            return null;
        }
        return copyList( videoIPage.getRecords());
    }


    /**
     * 用户点赞视频
     * @param videoId
     * @return
     */
    @Override
    public Result goodVideo(Integer videoId) {
//        increaseLikeCount(videoId);
        boolean flag = updateLikeCount(videoId);
        if(flag){
            return Result.success("点赞成功", null);
        }
        return Result.fail(403,"点赞失败");
    }

    /**
     * 批量转换VO
     * @param videoList
     * @return
     */
    public List<VideoVo> copyList(List<Video> videoList) {
        List<VideoVo> videoVoList = new ArrayList<>();
        for (Video video: videoList) {
            videoVoList.add( copy(video));
        }
        return videoVoList;
    }

    //转换单条数据
    private VideoVo copy(Video video) {
        VideoVo videoVo = new VideoVo();
        BeanUtils.copyProperties(video, videoVo);
        String userAccount = video.getUserAccount();
        User user = userService.getUserByAccount(userAccount);
        Category category = categoryService.getCategoryById(video.getCategoryId());
        //处理日期的字段
        videoVo.setCreateTime(TimeUtil.getDateTimeAsString(video.getCreateTime()));
        videoVo.setUserAccount(user.getAccount());
        videoVo.setUserAvatar(user.getAvatar());
        videoVo.setUserNickName(user.getNickName());
        videoVo.setCategoryName(category.getCategoryName());
        return videoVo;
    }

    @Override
    public void increasePlayCount(Integer videoId) {
        redisTemplate.opsForHash().increment(Constant.VIDEO_PLAY_COUNT_KEY_PREFIX,String.valueOf(videoId),1);
    }

    @Override
    public void increaseLikeCount(Integer videoId) {
        redisTemplate.opsForHash().increment(Constant.VIDEO_LIKE_COUNT_KEY_PREFIX,String.valueOf(videoId),1);
    }

    @Override
    public void increaseCommentCount(Integer videoId) {
        updateCommentCount(videoId);
//        redisTemplate.opsForHash().increment(Constant.VIDEO_COMMENT_COUNT_KEY_PREFIX,String.valueOf(videoId),1);
    }


    /**
     * 更新视频播放量
     * @param videoId
     * @param playCount
     * @return
     */
    @Override
    public boolean updatePlayCount(Integer videoId, Long playCount) {
        LambdaQueryWrapper<Video>queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Video::getVideoId, videoId);
        Video video = videoMapper.selectOne(queryWrapper);
        if(video==null){
            return false;
        }
        video.setPlayNum(video.getPlayNum() + playCount);
        videoMapper.update(video,queryWrapper);
        return true;
    }

    /**
     * 更新视频点赞量
     * @param videoId
     * @param likeCount
     * @return
     */
    @Override
    public boolean updateLikeCount(Integer videoId, Long likeCount) {
        LambdaQueryWrapper<Video>queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Video::getVideoId, videoId);
        Video video = videoMapper.selectOne(queryWrapper);
        if(video==null){
            return false;
        }
        video.setLikeNum(video.getLikeNum()+likeCount);
        videoMapper.update(video,queryWrapper);
        return true;
    }

    @Override
    public boolean updateLikeCount(Integer videoId) {
        LambdaQueryWrapper<Video>queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Video::getVideoId, videoId);
        Video video = videoMapper.selectOne(queryWrapper);
        if(video==null){
            return false;
        }
        video.setLikeNum(video.getLikeNum()+1);
        videoMapper.update(video,queryWrapper);
        return true;
    }


    /**
     * 更新视频点赞量
     * @param videoId
     * @param
     * @return
     */
    @Override
    public boolean updateCommentCount(Integer videoId, Long commentCount) {
        LambdaQueryWrapper<Video>queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Video::getVideoId, videoId);
        Video video = videoMapper.selectOne(queryWrapper);
        if(video==null){
            return false;
        }
        video.setCommentNum(video.getCommentNum()+commentCount);
        videoMapper.update(video,queryWrapper);
        return true;
    }

    @Override
    public boolean updateCommentCount(Integer videoId) {
        LambdaQueryWrapper<Video>queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Video::getVideoId, videoId);
        Video video = videoMapper.selectOne(queryWrapper);
        if(video==null){
            return false;
        }
        video.setCommentNum(video.getCommentNum()+1);
        videoMapper.update(video,queryWrapper);
        return true;
    }

    /**
     * 获取视频总页数
     * @param pageParams
     * @return
     */
    @Override
    public Long getVideoTotalPage(PageParams pageParams) {
        LambdaQueryWrapper<Video> queryWrapper = new LambdaQueryWrapper<>();
        if(pageParams.getCondition()!=null) {
            queryWrapper.eq(Video::getCategoryId, pageParams.getCondition());
        }
        Page<Video> page = new Page<>(pageParams.getPage(), pageParams.getPageSize());
        IPage<Video> videoIPage = videoMapper.selectPage(page, queryWrapper);
        return videoIPage.getTotal();
    }

    /**
     * 用户删除视频
     * @param videoId
     * @return
     */
    @Override
    public Result delete(Integer videoId, User user) {
        LambdaQueryWrapper<Video> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Video::getVideoId, videoId).eq(Video::getUserAccount, user.getAccount());
        Video video = videoMapper.selectOne(queryWrapper);
        if(video == null) {
            return Result.fail(ErrorCode.NO_EXIST_VIDEO.getCode(), ErrorCode.NO_EXIST_VIDEO.getMsg());
        }
        //删除云存储的文件
        String videoUrl = video.getVideoUrl();
        String key = "";
        int vidIndex = videoUrl.indexOf("/");
        if (vidIndex != -1) {
            key = videoUrl.substring(vidIndex);
            System.out.println(key);
        } else {
            System.out.println("VID not found in the string.");
            return Result.fail(ErrorCode.VIDEO_DELETE_FAIL.getCode(),ErrorCode.VIDEO_DELETE_FAIL.getMsg());
        }
        //删除云端视频文件
        boolean delete = qiniuUtils.delete(key);
        if(!delete){
            return Result.fail(ErrorCode.VIDEO_DELETE_FAIL.getCode(),ErrorCode.VIDEO_DELETE_FAIL.getMsg());
        }
        //删除DB记录
        videoMapper.delete(queryWrapper);
        return Result.success("删除成功",null);
    }
    /**
     * 获取最热视频
     * @param size
     * @return
     */
    @Override
    public List<VideoVo> getHotVideoList(Integer size) {
        LambdaQueryWrapper<Video> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.orderByDesc(Video::getCollectNum)
                .orderByDesc(Video::getCommentNum)
                .orderByDesc(Video::getLikeNum)
                .orderByDesc(Video::getPlayNum);
        queryWrapper.last("limit " + size);
        List<Video> videoList = videoMapper.selectList(queryWrapper);
        return copyList(videoList);
    }

    /**
     * 当前视频的后size条
     * @param size
     * @return
     */
    @Override
    public List<VideoVo> getCurrentVideo( Integer videoId, Integer size) {
        LambdaQueryWrapper<Video> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(Video::getVideoId, videoId);


        queryWrapper.last("limit " + size);
        List<Video> videoList = videoMapper.selectList(queryWrapper);
        return copyList(videoList);
    }

    @Override
    public List<Integer> getAllVideo() {
        LambdaQueryWrapper<Video> queryWrapper = new LambdaQueryWrapper<>();
        List<Video> videoList = videoMapper.selectList(queryWrapper);
        List<Integer> idList = new ArrayList<>();
        for (Video video : videoList) {
            idList.add(video.getVideoId());
        }
        return idList;
    }
}
